merge: integrate clusterfuck branch (40 commits)#97
Merged
Conversation
…reaker Auto-negotiation between two TUN-capable nodes currently deadlocks at Indeterminate. The new `interactive` field in `Capabilities` lets a node signal "human at terminal", which the negotiation logic (next commit) uses as a deterministic tiebreaker. All existing Capabilities struct literals default to `interactive: false`. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…aker When both peers are TUN-capable, the interactive flag (human at terminal) breaks the deadlock deterministically. Adds reason field to Resolved variant for traceability. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Auto-mode detects whether stdin is a terminal and advertises it in the handshake. Explicit modes always set interactive=false since their role is predetermined. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…address Previously all accepted relay peers were registered with their socket address as name and NodeRole::Relay hardcoded. Now extracts the peer's configured name and derives role from advertised capabilities, matching how entry/exit modes register peers. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Source and accepted peers had no heartbeat — no latency tracking, no liveness checks, and disconnect_peer IPC couldn't reach them. Spawns heartbeat for both connection paths. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ent daemons Multiple daemon instances on the same host (e.g. entry + relay) previously fought over a single wallhackd.sock. The daemon now derives a socket filename from the mode name (wallhackd-entry.sock, wallhackd-relay.sock, etc.). The WALLHACK_HOST env var and -H flag still override for explicit addressing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
node_state.update_capabilities in auto mode now reflects the actual interactive flag instead of hardcoding false — status API no longer misreports what was advertised in the handshake. REPL path uses the mode-derived socket name, matching the headless path so concurrent REPL-attached daemons no longer collide. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The existing `disconnect` command kills the entire transport session. `disconnect-peer <name>` surgically drops a single peer connection, which is the intended operation when managing multi-peer topologies. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
MCP agents can now steer auto-negotiation without CLI access via set_hint (prefer/exclude/fixed) and clear_hints tools. The status→info rename aligns MCP with the CLI naming convention: info = node identity, stats = traffic counters. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Headless orchestration (CI, monitoring, MCP fallback) previously required IPC for connect/listen/disconnect/ping/shutdown/hints. All operations are now available over HTTPS with the same auth model. The /status→/info rename aligns with CLI and MCP naming: info = identity, stats = traffic. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace "upstream" in DisconnectCmd doc with neutral terminology. Rename single-char match bindings (c, l, p) to descriptive names (connect, listen, ping) in new API handlers per naming standard. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
A TUN-capable node connecting to the listen side of a relay incorrectly resolved to Entry — the negotiate() function couldn't distinguish which side of the relay chain the connector was on since the relay's handshake was identical in both directions. The relay now sends Fixed(Entry) in its accept-side handshake, declaring "I represent the entry side." negotiate() respects peer FIXED hints before capability rules, so the accepted peer takes the complement and resolves to Exit. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All three interfaces now use the same pattern: disconnect with an optional peer argument. Omitting the peer disconnects the transport; providing one disconnects that specific peer. Removes the separate disconnect-peer subcommand/tool that broke parity with the REPL. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
route_add/route_remove and hint_set/hint_clear now mirror the REPL's "route add" / "route remove" and "hint set" / "hint clear" verb order instead of the inverted add_route/set_hint form. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
"auto" communicates intent — return to capability-based negotiation — rather than the mechanism (clearing a data structure). REPL keeps "clear" as a hidden alias for muscle memory. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ntion Pre-1.0 rename to establish noun_verb ordering (RouteAddRequest, HintSetRequest, PeerDisconnectRequest) matching the CLI/REPL/MCP command structure. StatusRequest/Response renamed to Info to match the endpoint rename. ClearHints renamed to HintAuto. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…roto and all consumers iproute2-style `del` instead of `remove`. HintSetAuto sits in the HintSet family — clearing hints is setting the negotiation mode to auto. No aliases — one name per operation across REPL, CLI, MCP, and REST. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…m terminal build_local_handshake now takes a Capabilities struct instead of positional bools — call sites are self-documenting. All modes (entry/exit/relay/auto) derive interactive from stdin terminal detection instead of hardcoding false. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ed tasks Deduplicates handshake→name/role extraction into resolve_peer(). Spawned task clones use block-scoped shadowing instead of _cleanup suffixes per naming standard. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
routeAdd/routeDel/hintSet/hintSetAuto match the proto and interface naming established in the wire rename. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
StatusResponse→InfoResponse, RouteAddRequest→RouteAddBody, SetHintRequest→HintSetBody. Web UI generates TypeScript types from these schema names, so they need to be consistent with the interface naming convention. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All Arc::clone bindings now shadow the original name in block scope instead of using _suffix or single-char names. Opaque abbreviations (pa, ns, ru, r, m, p, e, cc, lhs) replaced with descriptive names. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ility Relays can now announce accepted peers to their source peer via a new PeerAnnouncement message on the control stream. The entry sees peers behind the relay without direct transport connectivity. Control loop forwards announcements through a new peer_announcement_tx channel — wiring in the daemon modes is the next commit. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The relay subscribes to its own peer registry events and forwards PeerAnnouncement messages over the existing control stream to the source peer. The server-side control loop registers announced peers directly in the entry's registry — no new channels or transport needed. Entry nodes now see peers behind relays in their peers list. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ived role The relay's accept-side handshake forces all accepted peers to Exit via Fixed(Entry) hint. The peer registry and announcement must reflect the negotiated role, not the raw capability guess (which incorrectly shows TUN-capable peers as Entry). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The send-instructions task never exited because the fan-out channel stayed alive — peers were never unregistered. Move cleanup to the data-in task which exits when the peer's transport dies. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move peer unregistration from the dead send-instructions path to the data-in task which actually exits when the transport dies. Rename "Peer departed" log to "Peer disconnected (via relay)" for consistency. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
"connected with" / "disconnected from" instead of "Peer announced" / "Peer disconnected" — the receiving node didn't initiate the connection. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…g 404 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Empty HOME/USER/XDG_RUNTIME_DIR (common in minimal VMs) produced paths like /.wallhack/ instead of falling through to /tmp/wallhack-shared/. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Auto mode registered peers with default (all-false) capabilities. Now extracts capabilities from the peer's handshake and updates the registry. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The heartbeat loop exits when send_ping fails (control channel closed). This is the most reliable connection-death signal — unregister the peer here instead of relying on transport stream tasks that may not exit promptly. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…step default+update Previously callers would register with default capabilities then immediately call update_capabilities to set the real values from the handshake. Consolidate into a single atomic operation by requiring capabilities at register() time. Remove the now-dead update_capabilities method from Registry. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…iant Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The hint command was protocol jargon. All role operations now go through a single `role` command: `role entry` (hard set), `role prefer entry` (soft), `role exclude entry`, `role auto` (clear). Also renames ping_peer → peer_ping for noun_verb consistency. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…rfuck # Conflicts: # crates/api/src/handlers.rs # crates/api/src/lib.rs # crates/cli/src/bin/wallhack.rs # crates/cli/src/cli.rs # crates/cli/src/repl.rs # crates/core/src/client/quic/mod.rs # crates/core/src/client/ws/mod.rs # crates/core/src/ipc.rs # crates/core/src/node_api.rs # crates/core/src/server/quic/mod.rs # crates/core/src/server/ws/mod.rs # crates/core/src/transport/protocol.rs # crates/daemon/src/mode/auto.rs # crates/daemon/src/mode/entry.rs # crates/daemon/src/mode/exit.rs # crates/daemon/src/mode/relay.rs # crates/mcp/src/tools.rs # crates/wire/proto/management.proto # website/src/data/openapi.json
The clusterfuck branch added /ping and /ping/{peer} REST endpoints.
Ping was removed in v0.12.0 — drop the handlers, routes, and
PingResponseBody struct.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Integrates the
clusterfuckbranch that was pushed but never PR'd/merged. 40 commits, 16 merge conflicts resolved.hintcommand eliminated — unified intorole(role entry/prefer/exclude/auto)Conflicts resolved by keeping main's newer infrastructure (logs feature, neli 0.7, PskFailTracker removal, client→source rename, deduped QUIC/WS client/server) while integrating clusterfuck's refactors.
How to verify
just checkpasses🤖 Generated with Claude Code